%%% -------------------------------------------------------------------
%%% Author  : Dmitriid
%%% Description : 
%%%
%%% Created : 25.09.2006
%%% -------------------------------------------------------------------
-module(janus_ws).

-behaviour(gen_server).
%% --------------------------------------------------------------------
%% Include files
%% --------------------------------------------------------------------

-include("./../include/JanusAT.hrl").

%% --------------------------------------------------------------------
%% External exports
-export([start/1, stop/0]).
-export([set_options/1, get_forum_list/0, get_option/2, ets/1]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

-record(state, {opts_table}).

-define(SERVER,?MODULE).
-define(URL, "http://rsdn.ru/ws/JanusAT.asmx").

%% ====================================================================
%% External functions
%% ====================================================================

ets(T) ->
    ets:info(T).

start(PathToConfig) ->
    ServerStarted = case gen_server:start_link({local, janus_ws}, janus_ws, [], []) of
                        {ok, _PID} ->
                            ok;
                        {error, {already_started, _PID}} -> 
                            ok;
                        {error, Reason} -> 
                            {error, Reason}
                    end,
	case ServerStarted of
            ok ->
                gen_server:call(?SERVER,{start_soap, {path_to_config, PathToConfig}});
            {error, FailureReason} ->
                {error, FailureReason}
    end.
	

stop() ->
    janus_ws:terminate(normal, []).

set_options(OptionList) ->
    gen_server:call(?SERVER,{set_options, OptionList}). 

get_forum_list() ->
    gen_server:call(?SERVER,get_forum_list,infinity). 


%% ====================================================================
%% Server functions
%% ====================================================================

%% --------------------------------------------------------------------
%% Function: init/1
%% Description: Initiates the server
%% Returns: {ok, State}          |
%%          {ok, State, Timeout} |
%%          ignore               |
%%          {stop, Reason}
%% --------------------------------------------------------------------
init([]) ->    
    R = {ok, #state{opts_table = ets:new(janus_ws_opts, [])}},
    io:format("~p~n", [R]),
    ets:all(),
    R.

%% --------------------------------------------------------------------
%% Function: handle_call/3
%% Description: Handling call messages
%% Returns: {reply, Reply, State}          |
%%          {reply, Reply, State, Timeout} |
%%          {noreply, State}               |
%%          {noreply, State, Timeout}      |
%%          {stop, Reason, Reply, State}   | (terminate/2 is called)
%%          {stop, Reason, State}            (terminate/2 is called)
%% --------------------------------------------------------------------
handle_call({set_options, OptionList}, _From, State) ->
    inner_set_options(OptionList, State),
    {reply, ok, State};

handle_call({start_soap, {path_to_config, PathToConfig}}, _From, State) ->
    inner_set_options([{path_to_config, PathToConfig}], State),
    {reply, start_soap(State), State};

handle_call(get_forum_list, _From, State) ->  
    Options = get_proxy_details(State),  
    User = get_option(login, State),  
    Pass = get_option(password, State),  
    SoapReply = case soapclient:invoke(?URL,
                           "\"http://rsdn.ru/Janus/GetForumList\"",
                           #'p:GetForumList'{'forumRequest'=#'p:ForumRequest'{userName=User, password=Pass}}, 
                           {ibrowse, Options, []}) of
        {ok, Reply} -> Reply;
        {error, Error} -> {error, Error}
	end,
    {reply, SoapReply, State}.

%% --------------------------------------------------------------------
%% Function: handle_cast/2
%% Description: Handling cast messages
%% Returns: {noreply, State}          |
%%          {noreply, State, Timeout} |
%%          {stop, Reason, State}            (terminate/2 is called)
%% --------------------------------------------------------------------
handle_cast(Msg, State) ->
    {noreply, State}.

%% --------------------------------------------------------------------
%% Function: handle_info/2
%% Description: Handling all non call/cast messages
%% Returns: {noreply, State}          |
%%          {noreply, State, Timeout} |
%%          {stop, Reason, State}            (terminate/2 is called)
%% --------------------------------------------------------------------
handle_info(Info, State) ->
    {noreply, State}.

%% --------------------------------------------------------------------
%% Function: terminate/2
%% Description: Shutdown the server
%% Returns: any (ignored by gen_server)
%% --------------------------------------------------------------------
terminate(Reason, State) ->
    ok.

%% --------------------------------------------------------------------
%% Func: code_change/3
%% Purpose: Convert process state when code is changed
%% Returns: {ok, NewState}
%% --------------------------------------------------------------------
code_change(OldVsn, State, Extra) ->
    {ok, State}.

%% --------------------------------------------------------------------
%%% Internal functions
%% --------------------------------------------------------------------

inner_set_options([], _) ->
    [];
inner_set_options([Option|OptionList], State) ->
    ets:insert(State#state.opts_table, Option),
    inner_set_options(OptionList, State).

get_option(Option, State) ->
	case ets:lookup(State#state.opts_table, Option) of
            [{Option, Val}] ->
                Val;
            _ ->
                ""
	end.

get_proxy_details(State) ->    
    ProxyHost = get_option(proxy_host, State),
    ProxyPort = get_option(proxy_port, State),
    ProxyUser = get_option(proxy_user, State),
    ProxyPass = get_option(proxy_password, State),
    
    [case ProxyHost of
         "" -> [];
         Host -> {proxy_host, Host}
     end] ++
    [case ProxyPort of
         "" -> [];
         Port -> {proxy_port, Port}
     end] ++
    [case ProxyUser of
         "" -> [];
         User -> {proxy_user_name, User}
     end] ++
    [case ProxyPass of
         "" -> [];
         Pass -> {proxy_host, Pass}
     end].
            
start_soap(State) ->
    PathToConfig = get_option(path_to_config, State),
	case 
        case soap_registry_server:start(PathToConfig ++ "soap-envelope.xsd") of
            {ok,_Pid} -> ok;
            {error, {already_started, _Pid}} -> ok;
            OtherErr -> OtherErr
        end 
        of
            ok -> soap_registry_server:add_xsd(?URL, PathToConfig ++ "JanusAT.xsd");
            Other -> Other
        end.
